#include "myimageview.h"
#include "my_cv_imread.h"
#include <QGraphicsItem>
#include <QWheelEvent>

MyImageView::MyImageView(QWidget *parent) : QGraphicsView(parent), m_scene(new QGraphicsScene(this))
{
    setScene(m_scene);
}

bool MyImageView::showImage(cv::Mat image)
{
    if (image.depth() != CV_8U)
        return false;
    QImage qimgRenderNew;
    qimgRenderNew = QImage(
                image.data,
                image.cols,
                image.rows,
                (qsizetype) static_cast<size_t>(image.step),
                QImage::Format_Grayscale8);

    std::swap(m_imgRender, image);
    std::swap(m_qimgRender, qimgRenderNew);

    if (m_pixmapItem == nullptr) {
        qDebug()<<"null";
        m_pixmapItem =
                m_scene->addPixmap(QPixmap::fromImage(m_qimgRender));
        m_pixmapItem->setTransformationMode(Qt::TransformationMode::FastTransformation);
        show();
        zoom(MIN((double) QWidget::height() / m_imgRender.rows, (double) QWidget::width() / m_imgRender.cols));
    } else {
        m_pixmapItem->setPixmap(QPixmap::fromImage(m_qimgRender));
        show();
    }
    return true;
}

bool MyImageView::showImage(QImage image) {
    if (image.isNull())
        return false;
    // 1. Remove the old pixmap item if it exists.  Crucial step!
    if (m_pixmapItem != nullptr) {
        m_scene->removeItem(m_pixmapItem);
        delete m_pixmapItem; // VERY IMPORTANT: Delete the item to free memory
        m_pixmapItem = nullptr;
    }
    // 2. Efficiently update the image using std::swap (good optimization)
//    QImage qimgRenderNew(image);
//    std::swap(m_qimgRender, qimgRenderNew);
    if (m_pixmapItem == nullptr) {
        m_pixmapItem =
                m_scene->addPixmap(QPixmap::fromImage(image));
        qDebug()<<"Null";
        m_pixmapItem->setTransformationMode(Qt::TransformationMode::FastTransformation);
        show();
        zoom(MIN((double) QWidget::height() / m_imgRender.rows, (double) QWidget::width() / m_imgRender.cols));
    } else {
        m_pixmapItem->setPixmap(QPixmap::fromImage(m_qimgRender));
        show();
    }
    return true;
}



void MyImageView::zoom(double scaleFactor)
{
    setTransformationAnchor(QGraphicsView::AnchorViewCenter);
    qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
    if (factor < 0.01 || factor > 2000)
        return;
    scale(scaleFactor, scaleFactor);
}
/*
void MyImageView::mousePressEvent(QMouseEvent *event)
{
    if (!m_imgRender.empty()) {
        if (event->button() == Qt::MouseButton::LeftButton) {
            m_dragFlag = true;
            m_dragPos = event->pos();
            m_centerPosInScene = mapToScene(rect().center());
            event->accept();
            return;
        }
    }
    QGraphicsView::mousePressEvent(event);
}

void MyImageView::mouseReleaseEvent(QMouseEvent *event)
{
    m_dragFlag = false;
    if (!m_imgRender.empty()) {
        if (event->button() == Qt::MouseButton::LeftButton) {
            auto pos = mapToScene(event->pos());

            m_pix_site[0] = (int) pos.y();
            m_pix_site[1] = (int) pos.x();
            //    cv::Vec2i pix_site((int) pos.y(), (int) pos.x());
            if (0 <= m_pix_site[0] && m_pix_site[0] < m_imgRender.rows
                && 0 <= m_pix_site[1] && m_pix_site[1] < m_imgRender.cols) {
                if (m_imgRender.channels() == 1) {
                    auto pixbuf = m_imgRender.at<uchar>(m_pix_site[0], m_pix_site[1]);
                    m_pix_info.resize(1);
                    m_pix_info[0] = pixbuf;
                } else if (m_imgRender.channels() == 3) {
                    auto pixbuf = m_imgRender.at<cv::Vec3b>(m_pix_site[0], m_pix_site[1]);
                    m_pix_info.resize(3);
                    m_pix_info[0] = pixbuf[0];
                    m_pix_info[1] = pixbuf[1];
                    m_pix_info[2] = pixbuf[2];
                } else if (m_imgRender.channels() == 4) {
                    auto pixbuf = m_imgRender.at<cv::Vec4b>(m_pix_site[0], m_pix_site[1]);
                    m_pix_info.resize(4);
                    m_pix_info[0] = pixbuf[0];
                    m_pix_info[1] = pixbuf[1];
                    m_pix_info[2] = pixbuf[2];
                    m_pix_info[3] = pixbuf[3];
                }
            } else {
                m_pix_info = std::vector<uint8_t>(4, 0);
            }
            if (!m_moveFlag)
                    emit pixelInfo(m_pix_site, m_pix_info);
            event->accept();
            m_moveFlag = false;
            return;
        }
    }
    m_moveFlag = false;
    QGraphicsView::mousePressEvent(event);
}

void MyImageView::mouseMoveEvent(QMouseEvent *event)
{
    if (!m_imgRender.empty()) {
        if (m_dragFlag) {
            m_moveFlag = true;
            QPointF mouseDelta = mapToScene(event->pos()) - mapToScene(m_dragPos);
//            SPDLOG_TRACE("x={},y={}", mouseDelta.x(), mouseDelta.y());
            this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
            this->centerOn(m_centerPosInScene - mouseDelta);
        }
        event->accept();
        return;
    }
    QGraphicsView::mousePressEvent(event);
}

void MyImageView::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (m_imgRender.empty()) {
        return;
    }
    zoom(1.0);
}*/
void MyImageView::wheelEvent(QWheelEvent *event)
{
    double scale_rate = event->angleDelta().y() > 0 ? 1.3 : (1.0 / 1.3);
    zoom(scale_rate);
}
